package com.ctl.utils.cron;

import org.springframework.beans.BeanUtils;
import org.springframework.scheduling.support.CronExpression;

import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;

/**
 * <p>Title: 时间转cron表达式</p >
 * <p>Description: </p >
 * <p>Copyright: Copyright (c) 2022</p >
 * <p>Company: www.ctl.com</p >
 *
 * @author ctl
 * @version 1.1
 * @date 2022-04-21 09:50
 */
public class CronUtil {
    /**
     * 方法摘要：构建Cron表达式
     *
     * @param taskScheduleModel
     * @return String
     */
    public static String createCronExpression(TaskScheduleModel taskScheduleModel) throws Exception {

        //拆分时间字符串 年，月，日，时，分，秒
        String[] split1 = taskScheduleModel.getStartDate().split(" |-|:");
        StringBuffer cronExp = new StringBuffer("");
        if (null == taskScheduleModel.getJobType()) {
            System.out.println("执行周期未配置");//执行周期未配置
        }
        if (null != split1[5] && null != split1[4] && null != split1[3]) {
            if (taskScheduleModel.getJobType().intValue() == TaskScheduleModel.Types.T0.getType()) { //每分钟
                //秒
                cronExp.append(split1[5]).append(" ");
                //每分钟
                cronExp.append("* ").append(" ");
                cronExp.append("* ");//小时
                cronExp.append("* ");//日
                cronExp.append("* ");//月
                cronExp.append("?");//周
            } else if (taskScheduleModel.getJobType().intValue() == TaskScheduleModel.Types.T1.getType()) { //每小时
                //秒
                cronExp.append(split1[5]).append(" ");
                //分
                cronExp.append(split1[4]).append(" ");
                //每小时
                cronExp.append("* ");//小时
                cronExp.append("* ");//日
                cronExp.append("* ");//月
                cronExp.append("?");//周
            } else if (taskScheduleModel.getJobType().intValue() == TaskScheduleModel.Types.T2.getType()
                    || taskScheduleModel.getJobType().intValue() == TaskScheduleModel.Types.T3.getType()
                    || taskScheduleModel.getJobType().intValue() == TaskScheduleModel.Types.T4.getType()
                    || taskScheduleModel.getJobType().intValue() == TaskScheduleModel.Types.T5.getType()) { //每天
                //秒
                cronExp.append(split1[5]).append(" ");
                //分
                cronExp.append(split1[4]).append(" ");
                //时
                cronExp.append(split1[3]).append(" ");
            } else if (taskScheduleModel.getJobType().intValue() == TaskScheduleModel.Types.T6.getType()) { //每秒
                //秒
                cronExp.append("0/").append(split1[5]).append(" ");
                //每分钟
                cronExp.append("* ").append(" ");
                cronExp.append("* ");//小时
                cronExp.append("* ");//日
                cronExp.append("* ");//月
                cronExp.append("?");//周
            }

            //按每日
            if (taskScheduleModel.getJobType().intValue() == TaskScheduleModel.Types.T2.getType()) {

                cronExp.append("* ");//日
                cronExp.append("* ");//月
                cronExp.append("?");//周
            } else if (taskScheduleModel.getJobType().intValue() == TaskScheduleModel.Types.T3.getType()) { //按每周

//                String[] split2 = taskScheduleModel.getStartDate().split(" ")[0].split("-");
                Calendar instance = Calendar.getInstance();//创建格林威治时间
                instance.set(Integer.parseInt(split1[0]), Integer.parseInt(split1[1]) - 1, Integer.parseInt(split1[2]));
//                instance.setTime(date);//将传来的时间设置到格林威治时间内
                int dayForWeek = instance.get(Calendar.DAY_OF_WEEK) - 1;
                //获取本周的周几
//                int dayForWeek = DataUtils.dayForWeek(split2[0]);
                //一个月中第几天
                cronExp.append("? ");
                //月份
                cronExp.append("* ");
                //周
                cronExp.append(dayForWeek + 1);
            } else if (taskScheduleModel.getJobType().intValue() == TaskScheduleModel.Types.T4.getType()) { //按每月

                //一个月中的哪几天
                cronExp.append(split1[2]);
                //月份
                cronExp.append(" * ");
                //周
                cronExp.append("?");
            } else if (taskScheduleModel.getJobType().intValue() == TaskScheduleModel.Types.T5.getType()) { //按每年

                //一个月中的哪几天
                cronExp.append(split1[2]).append(" ");
                //月份
                cronExp.append(split1[1]).append(" ");
                //周
                cronExp.append("?");
            }

        } else {
            System.out.println("时或分或秒参数未配置");//时或分或秒参数未配置
        }
        return cronExp.toString();
    }

    public static Date localDateTimeToDate(LocalDateTime localDateTime) {
        Instant instant = localDateTime.atZone(ZoneId.systemDefault()).toInstant();
        Date date = Date.from(instant);
        return date;
    }

    public static LocalDateTime dateToLocalDateTime(Date date) {
        LocalDateTime localDateTime = LocalDateTime.ofInstant(Instant.ofEpochMilli(date.getTime()), ZoneId.systemDefault());
        return localDateTime;
    }

    public static Date getNextExecDateByCron(String cron) {
        final CronExpression cronExpression = CronExpression.parse(cron);
        final LocalDateTime dateTime = cronExpression.next(LocalDateTime.now());
        return localDateTimeToDate(dateTime);
    }

    public static Date localDateTimeToDatePlusMinutes(int minutes) {
        LocalDateTime localDateTime = LocalDateTime.now();
        System.out.println(localDateTime);
        localDateTime = localDateTime.plusMinutes(minutes);
        System.out.println(localDateTime);
        Instant instant = localDateTime.atZone(ZoneId.systemDefault()).toInstant();
        Date date = Date.from(instant);
        return date;
    }

    public static Date localDateTimeToDateMinusMinutes(int minutes) {
        LocalDateTime localDateTime = LocalDateTime.now();
        System.out.println(localDateTime);
        localDateTime = localDateTime.minusMinutes(minutes);
        System.out.println(localDateTime);
        Instant instant = localDateTime.atZone(ZoneId.systemDefault()).toInstant();
        Date date = Date.from(instant);
        return date;
    }


    public static LocalDateTime getNextExecDateByCron(String cron, Integer times) {
        try {
            final CronExpression cronExpression = CronExpression.parse(cron);
            LocalDateTime timeAfter = cronExpression.next(LocalDateTime.now());
            if (times == null || times <= 0) {
                times = 1;
            }
            for (int i = 2; i <= times; i++) {
                timeAfter = cronExpression.next(timeAfter);
            }
            return timeAfter;
        } catch (Exception e) {
            return null;
        }
    }

    public static List<LocalDateTime> getNextExecDateByCronAndTimes(String cron, Integer times) {
        List<LocalDateTime> dateList = new ArrayList<>();
        if (times == null || times <= 0) {
            times = 1;
        }
        final CronExpression cronExpression = CronExpression.parse(cron);
        LocalDateTime timeAfter = cronExpression.next(LocalDateTime.now());
        LocalDateTime date = LocalDateTime.now();
        BeanUtils.copyProperties(timeAfter, date);
        dateList.add(date);
        for (int i = 2; i <= times; i++) {
            LocalDateTime timeAfterT = cronExpression.next(timeAfter);
            LocalDateTime dateT = LocalDateTime.now();
            BeanUtils.copyProperties(timeAfterT, dateT);
            dateList.add(dateT);
            timeAfter = timeAfterT;
        }
        return dateList;
    }

    public static void main(String[] args) {
        TaskScheduleModel scheduleModel = new TaskScheduleModel();
//        for (int i = 0; i <= 6; i++) {
        for (int i = 2; i <= 2; i++) {
            scheduleModel.setJobType(i);
            scheduleModel.setStartDate("2022-12-21 09:01:05");
            try {
                String ce = createCronExpression(scheduleModel);
//                System.out.println("i="+i+"\t"+cronExpression);
//                System.out.println(ce);
                final CronExpression cronExpression = CronExpression.parse(ce);
                final LocalDateTime dateTime = cronExpression.next(LocalDateTime.now());
                System.out.println(ce + "\t" + dateTime.toString().replaceAll("T", " "));
                System.out.println(ce + "\t" + localDateTimeToDate(dateTime));
                System.out.println(ce + "\t" + localDateTimeToDate(dateTime));
                System.out.println(ce + "\t" + getNextExecDateByCron(ce));
                System.out.println(ce + "\t" + getNextExecDateByCron(ce,3));
//                System.out.println(new SimpleDateFormat("YYYY-MM-DD HH:mm:ss").format(new Date()));
//                System.out.println(new SimpleDateFormat("YYYY-MM-DD HH:mm:ss").format(new Date()));
            } catch (Exception e) {
                e.printStackTrace();
            }
        }

    }

}
